﻿using HandyControl.Themes;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using WpfMvvmTemplate.HC.Common;
using WpfMvvmTemplate.HC.ViewModels;
using WpfMvvmTemplate.HC.Views;

namespace WpfMvvmTemplate.HC
{
    public partial class App : Application
    {
        //IOC容器
        public IServiceProvider Services { get; }

        public App()
        {
            Services = ConfigureServices();

            #region 全局异常捕获

            //UI线程未捕获异常处理事件（UI主线程）
            this.DispatcherUnhandledException += (s, e) =>
            {
                if(e.Exception is Exception ex)
                {
                    Services.GetService<ILogger>()!.Error($"{ex.ToString()}");
                    e.Handled = true;//表示异常已处理，可以继续运行
                }
            };

            //非UI线程未捕获异常处理事件(例如自己创建的一个子线程)
            AppDomain.CurrentDomain.UnhandledException += (s, e) =>
            {
                if(e.ExceptionObject is Exception ex)
                    Services.GetService<ILogger>()!.Error(ex.ToString());
            };

            //Task线程内未捕获异常处理事件
            TaskScheduler.UnobservedTaskException += (s, e) =>
            {
                if(e.Exception is Exception ex)
                {
                    Services.GetService<ILogger>()!.Error($"{ex.ToString()}");
                    e.SetObserved(); // 标记异常已被处理，避免程序崩溃
                }
            };

            #endregion 全局异常捕获

            #region 单实例运行

            //判断程序是否已经启动
            var ProcessName = Assembly.GetExecutingAssembly().GetName().Name;//程序集名称
            Process currentProcess = Process.GetCurrentProcess();//当运行的新进程

            // 通过程序集名称判断是否有进程已运行
            Process[] ps = Process.GetProcessesByName(ProcessName);

            // 因为新进程名也是ProcessName，所以ps的Length大于1时才是有多个进程
            if(ps.Length > 1)
            {
                foreach(var item in ps)
                {
                    // 找到非当前新进程的 MessageConstruction 进程对象
                    if(item.Id != currentProcess.Id)
                    {
                        //关闭之前的进程
                        item.Kill();
                    }
                }
            }

            #endregion 单实例运行
        }

		//切换主题
        internal void UpdateTheme(ApplicationTheme theme)
        {
            if(ThemeManager.Current.ApplicationTheme != theme)
            {
                ThemeManager.Current.ApplicationTheme = theme;
            }
        }

		//切换颜色
        internal void UpdateAccent(Brush accent)
        {
            if(ThemeManager.Current.AccentColor != accent)
            {
                ThemeManager.Current.AccentColor = accent;
            }
        }

        public new static App Current => (App)Application.Current;

        //容器注册
        private static IServiceProvider ConfigureServices()
        {
            var services = new ServiceCollection();

            services.AddSingleton<MainWindowViewModel>();
            services.AddSingleton<MainWindowView>(sp => new MainWindowView { DataContext = sp.GetService<MainWindowViewModel>() });

            //注册日志服务
            services.AddSingleton<ILogger>((s) =>
            {
                var date = DateTime.Now.ToString("yyyy-MM-dd");
                var logFile = Path.Combine("Logs/", date + ".txt");

                return new LoggerConfiguration()
                            .MinimumLevel.Debug()
                            .WriteTo.File(logFile, retainedFileCountLimit: null) //自动换行
                            .CreateLogger();
            });

            return services.BuildServiceProvider();
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            var mainWindow = Services.GetService<MainWindowView>();
            mainWindow?.Show();

            //记录软件启动模式
            string AppName = AppDomain.CurrentDomain.FriendlyName;

#if DEBUG
            GlobalStaticData.Logger.Information($"软件 {AppName} 以 Debug 模式启动！");
#else
            GlobalStaticData.Logger.Information($"软件 {AppName} 以 Release 模式启动！");
#endif
        }
    }
}